APP_INITIALIZER in Angular
What is an APP_INITIALIZER?
The APP_INITIALIZER
is a built in injection token available in angular. The purpose of APP_INITIALIZER
is to perform any initialization task when the application loads.
Mostly the APP_INITIALIZER
will be used to get the application's configuration details before the application is rendered by called the api. The best way to use it is by returning a promise
function, so that it will wait until any operation is done and the promise is resolved. Once the promise is resolved, then the application will be initialized.
Create a new angular project
Create a new angular application using angular cli command.
ng new angular-tutorial
Create a ConfigService
Create a service to hold the configuration details. Lets create the service in the services folder by the following angular cli command.
ng g s services/config
Open the config.service.ts
file and modify the code as below.
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
interface IConfig {
serverUrl: string;
}
export class ConfigService {
private config: IConfig = { serverUrl: '' };
constructor() { }
init(serverUrl: string) {
this.config.serverUrl = serverUrl;
console.log('Configuration has been set.');
}
getConfig() {
return this.config;
}
}
We have created a variable config
which will be holding the property serverUrl
. The init()
function is used to set the serverUrl
property and once the property has been set, then it will log Configuration has been set.
to the console.
The getConfig()
function is used to return the configuration in the config
variable.
Add APP_INITIALIZER in AppModule
Open the app.module.ts
file and modify the code as below.
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule, HttpClient } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing-module';
import { AppComponent } from './app.component';
import { APP_INITIALIZER } from '@angular/core';
import { ConfigService } from './services/config.service';
const initializeConfig = (configService: ConfigService, http: HttpClient) => {
return (): Promise<any> => {
return new Promise((resolve, reject) => {
http.get('https://reqres.in/api/users/2').toPromise()
.then((result: any) => {
console.log(result);
configService.init(result.ad.url);
return resolve('Success');
});
});
}
};
@NgModule({
declarations: [
AppComponent,
],
imports: [
AppRoutingModule,
HttpClientModule,
],
providers: [ConfigService,
{ provide: APP_INITIALIZER, useFactory: initializeConfig, deps: [ConfigService, HttpClient], multi: true }
],
bootstrap: [AppComponent]
})
export class AppModule { }
In the above code we have imported the APP_INITIALIZER
and the ConfigService
.
In order to use the APP_INITIALIZER
, we have to use the syntax as below.
{ provide: APP_INITIALIZER, useFactory: function, deps: [], multi: true/false }
The APP_INITIALIZER
as the value to the provide property.
The useFactory
property will take function as its value. The function can perform synchronous or asynchronous function.
The deps
property is an array that will hold the dependencies needed for the function and the multi parameter can be true
or false
.
By default it is false
. If it is set to false
, then we use a token more than once, the last to register will override all the previous tokens. i.e you can have only one provider for token.
If it is true
, then the new providers are added to the previously registered providers making it more than one provider for a token. The angular will execute all of them when the token in invoked.
In our code, we have provided intializeConfig()
function as the value to useFactory
parameter and provided ConfigService
and HttpClient
as the dependencies in deps
array and set the multi parameter to be true
.
Next, lets take a look at the initializeConfig
function
const initializeConfig = (configService: ConfigService, http: HttpClient) => {
return (): Promise<any> => {
return new Promise((resolve, reject) => {
http.get('https://reqres.in/api/users/2').toPromise()
.then((result: any) => {
console.log(result);
configService.init(result.ad.url);
return resolve('Success');
});
});
}
};
The initializeConfig()
function takes ConfigService
and HttpClient
as parameter in configService
and http
variable name respectively.
The initializeConfig()
function is going to return a function as result and that function is going to return a Promise.
Inside the function we make api call using http
variable and chain it to return it as promise using toPromise
.
Retrieve the value returned by promise
and call the init()
function of ConfigService
to set the config
. Then return a resolve with a Success
message.
Adding some log in AppComponent
Next, open the app.component.ts
file and inside its constructor add some console to verify that the APP_INITIALIZER
has been loaded initially.
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
constructor() {
console.log('App component loaded');
}
ngOnInit(): void {
}
}
Run your application using
ng serve --o
Press F12
and check out the console. It will make the api to log the result to the console. It displays logs as below
Configuration has been set.
App component loaded